﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.DataModel;
using YArchitech.LIB;
using YArchitech.MEP;
using YArchitech.Revit;

namespace YArchitech.Plumbing
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class LaySprinklers : IExternalCommand
	{
		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			if (commandData == null)
			{
				throw new System.ArgumentNullException();
			}
			UIApplication application = commandData.Application;
			UIDocument activeUIDocument = application.ActiveUIDocument;
			Document document = activeUIDocument.Document;
			Selection selection = activeUIDocument.Selection;
			if (!YJKRevitTools.ViewCheck(activeUIDocument, new List<ViewType>
			{
				(ViewType)1,
				(ViewType)2
			}))
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			HYEquipmentCommon hyequipmentCommon = new HYEquipmentCommon();
			ICollection<ElementId> allFamilyInstance = hyequipmentCommon.GetAllFamilyInstance(document, BuiltInCategory.OST_Sprinklers);
			SpaceFamilyDataReader spaceFamilyDataReader = new SpaceFamilyDataReader();
			FormLaySprinklerHead formLaySprinklerHead = new FormLaySprinklerHead(document);
			if (formLaySprinklerHead.ShowDialog() == DialogResult.Cancel)
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			Transaction transaction = null;
			Result result;
			try
			{
				transaction = new Transaction(document, "喷头批量布置");
				transaction.Start();
				SprinklersParam sprinklersPara = formLaySprinklerHead.sprinklersPara;
				LayAreaParameter layAreaParam = formLaySprinklerHead.layAreaParam;
				LayAreaParameter layAreaParamlx = formLaySprinklerHead.layAreaParamlx;
				LayLineParameter layLineParam = formLaySprinklerHead.layLineParam;
				LayMidParameter layMidParam = formLaySprinklerHead.layMidParam;
				FamilySymbol familySymbol;
				if (formLaySprinklerHead.CurrentBtn == 1)
				{
					familySymbol = formLaySprinklerHead.Fsymbol;
				}
				else
				{
					familySymbol = spaceFamilyDataReader.GetFamilySymbolByIdSubTran(sprinklersPara.Id, "Sprinkler", sprinklersPara.SymbolName, document, BuiltInCategory.OST_Sprinklers);
				}
				int layTerminalType = formLaySprinklerHead.layTerminalType;
				if (familySymbol == null)
				{
					result = Autodesk.Revit.UI.Result.Cancelled;
				}
				else
				{
					if (familySymbol != null)
					{
						ConnectHelper connectHelper = new ConnectHelper();
						if (layTerminalType == 5)
						{
							if (layAreaParamlx != null)
							{
								XYZ min = selection.PickPoint("选择起始点坐标，此点为矩形的一个对角点");
								XYZ max = selection.PickPoint("选择终止点坐标，此点为矩形的另一个对角点");
								SubTransaction subTransaction = new SubTransaction(document);
								subTransaction.Start();
								List<XYZ> list = new List<XYZ>();
								if (layAreaParamlx.LimitFlag == 1)
								{
                                    list = connectHelper.CalculateLayFamilyInstanceForLingXingXYZ(min, max, layAreaParamlx.RowCount, layAreaParamlx.ColCount, layAreaParamlx.Ratio, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (DisplayUnitType)2), sprinklersPara.BeiShu);
								}
								else
								{
                                    list = connectHelper.CalculateLaySprinklersForLingXingXYZ(min, max, layAreaParamlx.RowDistance, layAreaParamlx.ColDistance, layAreaParamlx.RowDistanceSide, layAreaParamlx.ColDistanceSide, layAreaParamlx.LessDistance, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (DisplayUnitType)2), sprinklersPara.BeiShu);
								}
								if (list != null && list.Count > 0)
								{
									connectHelper.LayFamilyInstance(list, familySymbol, document.ActiveView.GenLevel, 0, document);
								}
								else
								{
									MessageBox.Show("布置失败", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
								}
								subTransaction.Commit();
							}
							else
							{
								MessageBox.Show("布置失败，区域布置参数为空", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
							}
						}
						else if (layTerminalType == 3)
						{
							if (layAreaParam != null)
							{
								XYZ min2 = selection.PickPoint("选择起始点坐标，此点为矩形的一个对角点");
								XYZ max2 = selection.PickPoint("选择终止点坐标，此点为矩形的另一个对角点");
								SubTransaction subTransaction2 = new SubTransaction(document);
								subTransaction2.Start();
								List<XYZ> list2 = new List<XYZ>();
								if (layAreaParam.LimitFlag == 1)
								{
                                    list2 = connectHelper.CalculateLayFamilyInstanceXYZ(min2, max2, layAreaParam.RowCount, layAreaParam.ColCount, layAreaParam.Ratio, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (DisplayUnitType)2), sprinklersPara.BeiShu);
								}
								else if (layAreaParam.LimitFlag == 2)
								{
                                    list2 = connectHelper.CalculateLaySprinklersXYZ(min2, max2, layAreaParam.RowDistance, layAreaParam.ColDistance, layAreaParam.RowDistanceSide, layAreaParam.ColDistanceSide, layAreaParam.LessDistance, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (DisplayUnitType)2), sprinklersPara.BeiShu);
								}
								YJKMessageBox.Show(list2.Count.ToString());
								if (list2 != null && list2.Count > 0)
								{
									connectHelper.LayFamilyInstance(list2, familySymbol, document.ActiveView.GenLevel, 0, document);
								}
								else
								{
									MessageBox.Show("布置失败", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
								}
								subTransaction2.Commit();
							}
							else
							{
								MessageBox.Show("布置失败，区域布置参数为空", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
							}
						}
						else if (layTerminalType == 4)
						{
							if (layMidParam != null)
							{
								XYZ min3 = selection.PickPoint("选择起始点坐标，此点为矩形的一个对角点");
								XYZ max3 = selection.PickPoint("选择终止点坐标，此点为矩形的另一个对角点");
								List<XYZ> list3 = new List<XYZ>();
								if (layMidParam.Type == 1)
								{
									list3 = connectHelper.CalculateLayFamilyInstanceXYZ(min3, max3, layMidParam.RowCount, layMidParam.ColCount, layMidParam.LeftDistance, layMidParam.RightDistance, layMidParam.TopDistance, layMidParam.BottomDistance, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
								}
								else
								{
									list3 = connectHelper.CalculateLayFamilyInstanceXYZ(min3, max3, layMidParam.RowDistance, layMidParam.ColDistance, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
								}
								if (list3 != null && list3.Count > 0)
								{
									connectHelper.LayFamilyInstance(list3, familySymbol, document.ActiveView.GenLevel, 0, document);
								}
								else
								{
									MessageBox.Show("布置失败", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
								}
							}
							else
							{
								MessageBox.Show("布置失败，居中布置参数为空", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
							}
						}
						else
						{
							if (layTerminalType == 1)
							{
								for (;;)
								{
									try
									{
										if (layLineParam != null)
										{
											if (layLineParam.OneLine == 1)
											{
												ISelectionFilter selectionFilter = new DetailCurveAndModelCurveSelectionFilter();
												Reference reference = selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, selectionFilter, "请选择一条直线或者弧线");
												Element element = document.GetElement(reference);
												XYZ globalPoint = reference.GlobalPoint;
												if (element.Location is LocationCurve)
												{
													Curve curve = (element.Location as LocationCurve).Curve;
													SubTransaction subTransaction3 = new SubTransaction(document);
													subTransaction3.Start();
													List<XYZ> list4 = new List<XYZ>();
													if (curve is Line)
													{
														YJKLine hyline = new YJKLine(curve as Line);
														if (layLineParam.LimitFlag == 1)
														{
															list4 = hyline.GetLayLineXYZList(globalPoint, layLineParam.Count, layLineParam.Ratio, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
														}
														else
														{
															list4 = hyline.GetLayLineXYZList(globalPoint, UnitConvert.LengthToStd(layLineParam.Distance / 1000.0), UnitConvert.LengthToStd(layLineParam.DistanceSide / 1000.0), UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
														}
													}
													else if (curve is Arc)
													{
														YJKCurve hycurve = new YJKCurve(curve);
														if (layLineParam.LimitFlag == 1)
														{
															list4 = hycurve.GetLayLineXYZList(globalPoint, layLineParam.Count, layLineParam.Ratio, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
														}
														else
														{
															list4 = hycurve.GetLayLineXYZList(globalPoint, UnitConvert.LengthToStd(layLineParam.Distance / 1000.0), UnitConvert.LengthToStd(layLineParam.DistanceSide / 1000.0), UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
														}
													}
													if (list4 != null && list4.Count > 0)
													{
														connectHelper.LayFamilyInstance(list4, familySymbol, document.ActiveView.GenLevel, 0, document);
													}
													else
													{
														MessageBox.Show("布置失败", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
													}
													subTransaction3.Commit();
												}
											}
											else if (layLineParam.OneLine == 2)
											{
												XYZ xyz = selection.PickPoint("请选择一个点作为线段的起点");
												XYZ xyz2 = selection.PickPoint("请选择一个点作为线段的终点，终点和起点不能为同一个点");
												while (xyz.IsAlmostEqualTo(xyz2))
												{
													xyz2 = selection.PickPoint("请选择一个点作为线段的终点,终点和起点不能为同一个点");
												}
												XYZ globalPoint2 = new XYZ(xyz.X + 0.1, xyz.Y, xyz.Z);
												SubTransaction subTransaction4 = new SubTransaction(document);
												subTransaction4.Start();
												List<XYZ> list5 = new List<XYZ>();
												try
												{
													YJKLine hyline2 = new YJKLine(xyz, xyz2);
													if (layLineParam.LimitFlag == 1)
													{
														list5 = hyline2.GetLayLineXYZList(globalPoint2, layLineParam.Count, layLineParam.Ratio, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
													}
													else
													{
														list5 = hyline2.GetLayLineXYZList(globalPoint2, UnitConvert.LengthToStd(layLineParam.Distance / 1000.0), UnitConvert.LengthToStd(layLineParam.DistanceSide / 1000.0), UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
													}
												}
												catch (Exception)
												{
													subTransaction4.RollBack();
													throw new Exception("选择的线管过短，无法满足设置参数！");
												}
												if (list5 != null && list5.Count > 0)
												{
													connectHelper.LayFamilyInstance(list5, familySymbol, document.ActiveView.GenLevel, 0, document);
												}
												else
												{
													MessageBox.Show("布置失败", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
												}
												subTransaction4.Commit();
											}
										}
										else
										{
											MessageBox.Show("布置失败，沿线布置参数为空", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
										}
										continue;
									}
									catch (Autodesk.Revit.Exceptions.OperationCanceledException)
									{
										goto IL_927;
									}
									break;
								}
							}
							if (layTerminalType == 2)
							{
								ISelectionFilter selectionFilter2 = new DetailLineAndArcSelectionFilter();
								List<XYZ> list6;
								for (;;)
								{
									IList<Element> elemList = selection.PickElementsByRectangle(selectionFilter2, "请框选网格");
									list6 = new List<XYZ>();
									list6 = this.GetLayGridXYZList(elemList, UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
									if (list6 != null && list6.Count > 0)
									{
										break;
									}
									if (list6 == null || list6.Count <= 0)
									{
										MessageBox.Show("没有框选辅助线", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
									}
									else
									{
										MessageBox.Show("布置失败", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
									}
								}
								connectHelper.LayFamilyInstance(list6, familySymbol, document.ActiveView.GenLevel, 0, document);
							}
							else if (layTerminalType == 0)
							{
								transaction.Commit();
								try
								{
									activeUIDocument.PromptForFamilyInstancePlacement(familySymbol);
								}
								catch (Autodesk.Revit.Exceptions.OperationCanceledException)
								{
								}
								transaction.Start();
							}
						}
					}
					IL_927:
					document.Regenerate();
					ICollection<ElementId> allFamilyInstance2 = hyequipmentCommon.GetAllFamilyInstance(document, BuiltInCategory.OST_Sprinklers);
					IEnumerable<ElementId> enumerable = new List<ElementId>();
					enumerable = allFamilyInstance.Intersect(allFamilyInstance2);
					if (enumerable.Count<ElementId>() > 0)
					{
						foreach (ElementId item in enumerable)
						{
							allFamilyInstance2.Remove(item);
						}
					}
					new AuxiliaryLineOperate();
					SubTransaction subTransaction5 = new SubTransaction(document);
					subTransaction5.Start();
					foreach (ElementId elementId in allFamilyInstance2)
					{
						Element elementById = document.GetElementById(elementId);
						HYParametersSetting hyparametersSetting = new HYParametersSetting(application);
						Parameter parameter = (elementById as FamilyInstance).Symbol.GetParameter(BuiltInParameter.RBS_FP_SPRINKLER_K_FACTOR_PARAM);
						if (parameter != null)
						{
							parameter.Set(sprinklersPara.Kratio);
						}
						Parameter parameter2 = elementById.GetParameter("喷淋半径");
						if (parameter2 == null)
						{
							hyparametersSetting.SetSprinklersRudioShareParam();
							parameter2 = elementById.GetParameter("喷淋半径");
						}
						if (parameter2 != null)
						{
							parameter2.Set(UnitConvert.CovertToAPI(sprinklersPara.Radius * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
						}
						Parameter parameter3 = elementById.GetParameter("危险等级");
						if (parameter3 == null)
						{
							hyparametersSetting.SetSprinklersDangerShareParam();
							parameter3 = elementById.GetParameter("危险等级");
						}
						if (parameter3 != null)
						{
							parameter3.Set(sprinklersPara.Danger);
						}
						Parameter parameter4 = elementById.GetParameter("行间距");
						if (parameter4 == null)
						{
							hyparametersSetting.SetSprinklersRowDistanceShareParam();
							parameter4 = elementById.GetParameter("行间距");
						}
						if (parameter4 != null)
						{
							parameter4.Set(UnitConvert.CovertToAPI(sprinklersPara.RowDistance, (Autodesk.Revit.DB.DisplayUnitType)2));
						}
						Parameter parameter5 = elementById.GetParameter("列间距");
						if (parameter5 == null)
						{
							hyparametersSetting.SetSprinklersColDistanceShareParam();
							parameter5 = elementById.GetParameter("列间距");
						}
						if (parameter5 != null)
						{
							parameter5.Set(UnitConvert.CovertToAPI(sprinklersPara.ColDistance, (Autodesk.Revit.DB.DisplayUnitType)2));
						}
						Parameter parameter6 = elementById.GetParameter(BuiltInParameter.FAMILY_LEVEL_PARAM);
						if (parameter6 != null)
						{
							parameter6.Set(document.ActiveView.GenLevel.Id);
						}
						Parameter parameter7 = elementById.GetParameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
						if (formLaySprinklerHead.familyCategory != 5)
						{
							if (parameter7 != null)
							{
								parameter7.Set(UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
							}
						}
						else
						{
							LaySprinklerHelper.LayUpDownSprinkler(document, elementById, layTerminalType, sprinklersPara);
						}
						CreateProtectRange createProtectRange = new CreateProtectRange();
						if (sprinklersPara.Range && (int)document.ActiveView.ViewType != 4)
						{
							List<Element> collection = new List<Element>
							{
								elementById
							};
							createProtectRange.CreatActiveViewDetailCurve(document, collection, HyRangeCheckMajor.HyGPS);
						}
					}
					subTransaction5.Commit();
					transaction.Commit();
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = Autodesk.Revit.UI.Result.Succeeded;
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
				this.EndTransation(transaction, false);
				result = Autodesk.Revit.UI.Result.Failed;
			}
			finally
			{
				this.EndTransation(transaction, true);
			}
			return result;
		}

		private void EndTransation(Transaction tran, bool beSure)
		{
			if (tran != null)
			{
				TransactionStatus status = tran.GetStatus();
				if ((int)status == 1)
				{
					if (beSure)
					{
						tran.Commit();
						return;
					}
					tran.RollBack();
					return;
				}
				else if ((int)status == 5)
				{
					tran.RollBack();
				}
			}
		}

		private List<XYZ> GetLayGridXYZList(IList<Element> elemList, double offSet)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Element element in elemList)
			{
				if (element.Location is LocationCurve)
				{
					YJKCurve hycurve = new YJKCurve((element.Location as LocationCurve).Curve);
					foreach (Element element2 in elemList)
					{
						if (element.Id.IntegerValue != element2.Id.IntegerValue && element2.Location is LocationCurve)
						{
							List<XYZ> list2 = hycurve.IntersectionAllPoint((element2.Location as LocationCurve).Curve);
							if (list2 != null)
							{
								foreach (XYZ xyz in list2)
								{
									XYZ xyz2 = new XYZ(xyz.X, xyz.Y, offSet);
									if (list.Count < 1)
									{
										list.Add(xyz2);
									}
									else
									{
										bool flag = false;
										foreach (XYZ xyz3 in list)
										{
											if (xyz2.IsAlmostEqualTo(xyz3))
											{
												flag = true;
												break;
											}
										}
										if (!flag)
										{
											list.Add(xyz2);
										}
									}
								}
							}
						}
					}
				}
			}
			return list;
		}
	}
}
